package com.library.book.dao;

import com.framework.BaseDao;
import com.framework.Page;
import com.library.entity.Book;
import com.library.entity.BookClass;
import com.library.entity.Staff;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.springframework.stereotype.Repository;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/*
 *	className:BookDaoImpl
 *	description:Book的基本增删改查
 *	author:mhy
 *	date:2018年1月9日13:49:02
 */

@Repository
public class BookDaoImpl extends BaseDao<Book, Integer> {
	@Resource
	private SessionFactory sessionFactory;

	public void saveBook(Book b,String path,MultipartFile file){
		String contextPath = path;
		String imageFilePath = contextPath + "assets/images/books/" + b.getName();	//封面图片绝对路径
		String relativeImagePath = "assets/images/books/"+b.getName() +"/" + file.getOriginalFilename();//相对路径

		try {
			if(file.isEmpty()){
				b.setBookImage("assets/images/books/"+b.getName() +"/" + "no-image.jpg");
			}else {
				b.setBookImage(relativeImagePath);
			}

			//创建图片到目录
			File savedir = new File(imageFilePath);
			if(!savedir.exists()){
				savedir.mkdirs();
			}
			File f = new File(savedir,file.getOriginalFilename());
			FileOutputStream fops = null;
			try {
				if(file.isEmpty()){
					FileInputStream fips = new FileInputStream(new File(contextPath + "assets/images/no-image.jpg"));
					fops = new FileOutputStream(new File(imageFilePath + "/no-image.jpg"));
					byte flush[]  = new byte[1024];
					int len = 0;

					while(0<=(len=fips.read(flush))){
						fops.write(flush, 0, len);
					}

					fips.close();
				} else{
					fops = new FileOutputStream(f);
					fops.write(file.getBytes());
				}
				fops.close();
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}

			this.save(b);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/*********** 检索图书 *********/
	/* 精确查找 by bookName,bookClass 不分页*/
	public Book getBookByISBN(String ISBN){
		try {
			return this.findOne("from Book b where b.ISBN = ?",new Object[]{ISBN});
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	public List<Book> findByBookNameAndBookClass(String bookName,BookClass bookClass){
		try{
			return super.findByProperty("from Book b where b.bookName=? and b.bookClass=?", new Object[]{bookName,bookClass});
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}
	}
	/* 精确查找 by bookName,bookClass  分页*/
	public List<Book> findByBookNameAndBookClass(int pageNum,int pageSize,String bookName,BookClass bookClass){
		try{
			return super.findListByPage(pageNum,pageSize,"from Book b where b.bookName=? and b.bookClass=?", new Object[]{bookName,bookClass});
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}
	}


	/*查询图书 分页*/
	public Page<Book> findPageByProperty(int pageNum, int pageSize, Map paramsMap){
		int i = 0;
		int j = 0;
		String key;
		StringBuilder hql = new StringBuilder("from Book b");
		List<Object> params = new ArrayList();

		if(paramsMap.size() != 0){
			Iterator<String> it = paramsMap.keySet().iterator();
			hql.append(" where ");
			while (it.hasNext()) {
				key = it.next();
				params.add(paramsMap.get(key));

				if(j != 0){
					if(params.get(i) != null)
						hql.append(" and b."+ key + "=?");
					else{
						hql.append(" and b."+ key + " is null");
						params.remove(i);
						++j;
						continue;
					}
				} else{
					if(params.get(i) != null)
						hql.append(" b."+ key + "=?");
					else{
						hql.append(" b."+ key + " is null");
						params.remove(i);
						++j;
						continue;
					}
				}
				++i;
				++j;
			}
		}
		try{
			return super.findByPage(pageNum,pageSize,hql.toString(),params.toArray());
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}
	}

    /*查询图书 不分页*/
    public List<Book> findBooksByProperty( Map paramsMap){
		int i = 0;
		int j = 0;
		String key;
		StringBuilder hql = new StringBuilder("from Book b");
		List<Object> params = new ArrayList();

		if(paramsMap.size() != 0){
			Iterator<String> it = paramsMap.keySet().iterator();
			hql.append(" where ");
			while (it.hasNext()) {
				key = it.next();
				params.add(paramsMap.get(key));

				if(j != 0){
					if(params.get(i) != null)
						hql.append(" and b."+ key + "=?");
					else{
						hql.append(" and b."+ key + " is null");
						params.remove(i);
						++j;
						continue;
					}
				} else{
					if(params.get(i) != null)
						hql.append(" b."+ key + "=?");
					else{
						hql.append(" b."+ key + " is null");
						params.remove(i);
						++j;
						continue;
					}

				}
				++i;
				++j;
			}
		}
		try{
            return super.findByProperty(hql.toString(),params.toArray());
        }catch(Exception e){
            e.printStackTrace();
            return null;
        }
    }

	/*查询图书按照热度排序 不分页*/
	public List<Book> findBooksByPropertyAndHot(Map paramsMap,int num){
		int i = 0;
		int j = 0;
		String key;
		StringBuilder hql = new StringBuilder("from Book b");
		List<Object> params = new ArrayList();

		if(paramsMap.size() != 0){
			Iterator<String> it = paramsMap.keySet().iterator();
			hql.append(" where ");
			while (it.hasNext()) {
				key = it.next();
				params.add(paramsMap.get(key));

				if(j != 0){
					if(params.get(i) != null)
						hql.append(" and b."+ key + "=?");
					else{
						hql.append(" and b."+ key + " is null");
						params.remove(i);
						++j;
						continue;
					}
				} else{
					if(params.get(i) != null)
						hql.append(" b."+ key + "=?");
					else{
						hql.append(" b."+ key + " is null");
						params.remove(i);
						++j;
						continue;
					}
				}
				++i;
				++j;
			}	//while
			hql.append("order by b.borrowTimes desc,b.browseTimes desc");
		}
		try{
			Query query = this.sessionFactory.getCurrentSession().createQuery(hql.toString());
			query.setMaxResults(num);			//设置最大查询数量
			if (params != null && params.toArray().length > 0) {
				for (i = 0; i < params.toArray().length; i++) {
					query.setParameter(i, params.toArray()[i]);
				}
			}
			return query.list();
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}
	}

	/*精确查找 by author,bookClass  不分页*/
    public List<Book> findByAuthorAndBookClass(String author,BookClass bookClass){
        try{
            return super.findByProperty("from Book b where b.author=? and b.bookClass=?", new Object[]{author,bookClass});
        }catch(Exception e){
            e.printStackTrace();
            return null;
        }
    }

	/*精确查找 by bookName or author or publish,bookClass  不分页*/
    public List<Book> findByBookInfo(String bookName,String author,String publish,BookClass bookClass){
		try{
            return super.findByProperty("from Book b where (b.name=? or b.author=? or publish=?) and b.bookClass=?", new Object[]{bookName,author,bookClass});
        }catch(Exception e){
            e.printStackTrace();
            return null;
        }
    }

	/*精确查找 by bookName or author,bookClass  分页*/
	public Page<Book> findByBookInfo(int pageNum,int pageSize,String bookName,String author,BookClass bookClass){
		try{
			return super.findByPage(pageNum,pageSize,"from Book b where (b.name=? or b.author=?) and b.bookClass=?", new Object[]{bookName,author,bookClass});
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}
	}

    /*模糊查找 不分页*/
	public List<Book> findVagueByBookInfo(String bookName,String author,String publish,BookClass bookClass){
		try{
			if(!bookName.equals("")){
				bookName = new StringBuffer("%").append(bookName).append("%").toString();
			}else if(!author.equals("")){
				author = new StringBuffer("%").append(author).append("%").toString();
			}else {
				publish = new StringBuffer("%").append(author).append("%").toString();
			}
			return super.findByProperty("from Book b where (b.name like ? or b.author like ? or b.publish like ?) and b.bookClass=?", new Object[]{bookName,author,publish,bookClass});
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}
	}

	/*模糊查找 分页*/
	public Page<Book> findVagueByBookInfo(int pageNum,int pageSize,String bookName,String author,String publish,BookClass bookClass){
		try{
			if(!bookName.equals("")){
				bookName = new StringBuffer("%").append(bookName).append("%").toString();
			}else if(!author.equals("")){
				author = new StringBuffer("%").append(author).append("%").toString();
			} else{
				publish = new StringBuffer("%").append(author).append("%").toString();
			}
			return super.findByPage(pageNum,pageSize,"from Book b where (b.name like ? or b.author like ? or b.publish like ?) and b.bookClass=?",new Object[]{bookName,author,publish,bookClass});
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}
	}

	/*模糊查找*/
	public List<Book> findVagueByBookInfo(String bookName,String author,String publish){
		try{
			if(!bookName.equals("")){
				bookName = new StringBuffer("%").append(bookName).append("%").toString();
			}else if(!author.equals("")){
				author = new StringBuffer("%").append(author).append("%").toString();
			} else{
				publish = new StringBuffer("%").append(author).append("%").toString();
			}
			return super.findByProperty("from Book b where (b.name like ? or b.author like ? or b.publish like ?", new Object[]{bookName,author,publish});
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}
	}

	/*模糊查找 分页*/
	public Page<Book> findVagueByBookInfo(int pageNum,int pageSize,String bookName,String author,String publish){
		try{
			if(!bookName.equals("")){
				bookName = new StringBuffer("%").append(bookName).append("%").toString();
			}else if(!author.equals("")){
				author = new StringBuffer("%").append(author).append("%").toString();
			} else{
				publish = new StringBuffer("%").append(author).append("%").toString();
			}
			return super.findByPage(pageNum,pageSize,"from Book b where b.name like ? or b.author like ? or b.publish like ?", new Object[]{bookName,author,publish});
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}
	}

	/*查找条件图书数量 分页*/
	public Long findCountByProperty(Map paramsMap){
		int i = 0;
		int j = 0;
		String key;
		StringBuilder hql = new StringBuilder("from Book b");
		List<Object> params = new ArrayList();

		if(paramsMap.size() != 0){
			Iterator<String> it = paramsMap.keySet().iterator();
			hql.append(" where ");
			while (it.hasNext()) {
				key = it.next();
				params.add(paramsMap.get(key));

				if(j != 0){
					if(params.get(i) != null)
						hql.append(" and b."+ key + "=?");
					else{
						hql.append(" and b."+ key + " is null");
						params.remove(i);
						++j;
						continue;
					}
				} else{
					if(params.get(i) != null)
						hql.append(" b."+ key + "=?");
					else{
						hql.append(" b."+ key + " is null");
						params.remove(i);
						++j;
						continue;
					}
				}
				++i;
				++j;
			}
		}
		try{
			return this.getBooksCount(hql.toString(),params.toArray());
		}catch(Exception e){
			e.printStackTrace();
			return (long)0;
		}
	}

	/*按条件查询数量*/
	public Long getBooksCount(String hql,Object[] params){
		try{
			return super.findCountByPage("select count(*) " + hql,params);
		}catch(Exception e){
			e.printStackTrace();
			return (long)0;
		}
	}

	/***************操作图书***************/
	/*查找图书 by bookId*/
	public Book getBook(int bookId){
		try {
			Book p=this.get(bookId);
			return p;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}

	/*精确查找 分页*/
	public Page<Book> findByStaff(int pageNum,int pageSize,Staff staff){
		try{
			return super.findByPage(pageNum,pageSize,"from Book b where ? in elements(b.staffs)", new Object[]{staff});
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}
	}

	/*精确查找 分页*/
	public List<Book> findByStaff(Staff staff){
		try{
			return super.findByProperty("from Book b where ? in elements(b.staffs)", new Object[]{staff});
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}
	}

	/*更新图书*/
	public void updateBook(Book b){
		try {
			this.update(b);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	/*更新图书封面照片*/
	public void updateBookImage(Book b,String path,MultipartFile mFile){
		String contextPath = path;
		String oldImagePath = contextPath + b.getBookImage();	//旧封面图片文件路径
		String imageFilePath = contextPath + "assets/images/books/" + b.getName();	//文件夹路径
		String newImagePath = "assets/images/books/" + b.getName()+"/" + mFile.getOriginalFilename();//新封面图片相对路径
		File file;
		try {
			if(mFile.isEmpty()){
				b.setBookImage("assets/images/books/"+b.getName() +"/" + "no-image.jpg");
			}else {
				b.setBookImage(newImagePath);
			}

			//删除旧封面图片
			file = new File(oldImagePath);
			if(file.exists()){
				file.delete();
			}
			//创建新封面图片到目录
			File savedir = new File(imageFilePath);
			if(!savedir.exists()){
				savedir.mkdirs();
			}
			file = new File(savedir,mFile.getOriginalFilename());
			FileOutputStream fops = null;
			try {
				if(mFile.isEmpty()){
					FileInputStream fips = new FileInputStream(new File(contextPath + "assets/images/no-image.jpg"));
					fops = new FileOutputStream(new File(imageFilePath + "/no-image.jpg"));
					byte flush[]  = new byte[1024];
					int len = 0;

					while(0<=(len=fips.read(flush))){
						fops.write(flush, 0, len);
					}

					fips.close();
				} else{
					fops = new FileOutputStream(file);
					fops.write(mFile.getBytes());
				}
					fops.close();
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
			this.save(b);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	/*删除图书*/
	public void deleteBook(Book b,String path){
		String imagePath;
		String contextPath = path;
		String imageFilePath;
		File file;
		try {
			imagePath = b.getBookImage();
			imageFilePath = contextPath + imagePath;

			//删除图片
			file = new File(imageFilePath);
			if(file.exists()){
				file.delete();
			}

			//删除文件夹
			file = new File(imageFilePath.substring(0,imageFilePath.lastIndexOf('/')));
			if(file.exists()){
				file.delete();
			}

			this.delete(b);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}


}
